using System;
using System.Collections;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Utility;
using PHSRAG.WebControls;
using Helper=PHSRAG.WebControls.Helper;
using PageHeader = PHSRAG.Insight21.InsightWebControls.Header;
using Utils = PHSRAG.Insight21.InsightUtilities;

namespace PHSRAG.Insight21.Humans
{
    /// <summary>
    /// Displays a list of items pending on protocols the logged-in user has access to
    /// </summary>
    public partial class PendingApplicationsPage : GridPage
    {
        #region Constants

        private const string AnimalsSortColumn = "SubmissionDate";
        private const string AnnunciatorTitle = "The following error(s) occurred...";
        private const string ExcelReportControlFilePath = "../../Research/Reports/PendingApplicationsExcel.ascx";
        private const string features = "width=600,height=400,scrollbars=yes,resizable=yes,status=no";
        private const string HumansSortColumn = "ProtocolNumber";
        private const string ViewIRBNotesCommand = "ViewIRBNotes";
        private const string WorkFlowReportPage = "WorkFlowReport.aspx";

        #endregion

        #region Instance Variables (Private)

        //private string sortColumn;
        private bool sortAscending = false;

        #endregion

        #region Private Properties

        /// <summary>
        /// Get the PendingApplications (summary of PendingApplications) that the logged-in user has access
        ///  to.  The list of PendingApplications is maintained by the PendingApplicationSummaries business
        ///  object within its data container. The PendingApplicationSummaries object is cached.
        /// </summary>
        private ProtocolManager ProtocolManagerInstance
        {
            get
            {
                ProtocolManager protocolManager = ResultsCache;
                CommonSearchContext searchContext = (CommonSearchContext) PrevailingCachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                UserContext userContext = PrevailingCachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                if (protocolManager == null)
                {
                    protocolManager = new ProtocolManager(PrevailingCachePolicy);
                    protocolManager.SortAscending = sortAscending;
                    protocolManager.SortColumn = SortColumn ?? ((ModuleName == InsightUtilities.Constants.Modules.Humans) ? HumansSortColumn : AnimalsSortColumn);
                    Trace.Write("GetPendingApplicationIds");
                    protocolManager.GetPendingApplicationIds(
                        DataAccess.ConnectionString,
                        searchCriteria,
                        userContext.DomainUserId,
                        (ModuleName == InsightUtilities.Constants.Modules.Humans) ? Constants.ModuleType.Humans : Constants.ModuleType.Animals);
                    Trace.Write("Done::GetPendingApplicationIds");
                }
                return protocolManager;
            }
        }

        /// <summary>
        /// Get the module name (from the header control)
        /// </summary>
        private string ModuleName
        {
            get { return header.ModuleName; }
        }

        /// <summary>
        /// Gets the object stored in cache
        /// </summary>
        private ProtocolManager ResultsCache
        {
            get { return Policy.ResultsCache.GetObject(PrevailingCachePolicy, ProtocolManager.CacheKey) as ProtocolManager; }
        }

        /// <summary>
        /// Date of the last successful feed that ran to populate this data
        /// </summary>
        public string LastFeedRunDate
        {
            get
            {
                string lastFeedRunDate = string.Empty;
                object feedDates = Application[InsightUtilities.Constants.FeedType.Cachekey];
                DataTable feedRunDates = (feedDates != null) ? (DataTable) feedDates : ProtocolManager.LastFeedRunDate;
                if (feedRunDates != null && feedRunDates.Rows.Contains(InsightUtilities.Constants.FeedType.HumansFeed))
                {
                    lastFeedRunDate = ((DateTime) feedRunDates.Rows.Find(InsightUtilities.Constants.FeedType.HumansFeed).ItemArray[0]).ToString("MM/dd/yyyy");
                }
                return lastFeedRunDate;
            }
        }

        /// <summary>
        /// This property will set the respective subnavigation link to be highlighted(This control as such will be used for Activeprotocols and InactiveProtocols)
        /// </summary>
        public string SelectedSubNavigationLink
        {
            set
            {
                if (ModuleName == InsightUtilities.Constants.Modules.Humans)
                {
                    humansSubNavigation.SelectedLink = value;
                    humansSubNavigation.Visible = humansSearchContainer.Visible = true;
                    animalsSearchContainer.Visible = animalsSubNavigation.Visible = false;
                }
                else
                {
                    animalsSubNavigation.SelectedLink = value;
                    humansSubNavigation.Visible = humansSearchContainer.Visible = false;
                    animalsSearchContainer.Visible = animalsSubNavigation.Visible = true;
                }
            }
        }

        /// <summary>
        /// Gets the boolean value, to decide whether or not to load the grid
        /// </summary>
        public bool IsOkayToLoadGrid
        {
            get
            {
                CommonSearchContext searchContext = ((CachePage) Page).PrevailingCachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
                if (null == searchContext)
                {
                    return false;
                }

                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                UserContext userContext = ((CachePage) Page).PrevailingCachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;

                return !(userContext.ShouldPromptForProtocolSearch(ModuleName) && searchCriteria.Version <= 0);
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        public PendingApplicationsPage()
            : base(Keys.PendingApplicationsPageKey)
        {
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Turns on or off the visibility of the panel containing the grid; if On:
        /// Populates the datagrid with data and sets pagers' display
        /// </summary>
        private void LoadDataGrid()
        {
            try
            {
                Trace.Write("Get PM Instance");
                ProtocolManager protocolManager = ProtocolManagerInstance;
                if (protocolManager.Count > 0)
                {
                    topPager.Visible = bottomPager.Visible = true;
                    pendingItems.VirtualItemCount =
                        bottomPager.RecordCount = topPager.RecordCount =
                            protocolManager.Count;
                    pageLabel.Text = String.Format("{0} {1} | As Of {2}", protocolManager.Count,
                        "Pending Applications", LastFeedRunDate);
                    int currentPageIndex = CurrentPageIndex;
                    int pageCount = (topPager.RecordCount/pendingItems.PageSize) +
                        (((topPager.RecordCount%pendingItems.PageSize) == 0) ? 0 : 1);
                    bottomPager.PageCount = topPager.PageCount = pageCount;
                    bottomPager.CurrentPage = topPager.CurrentPage = currentPageIndex + 1;
                    UserContext userContext = PrevailingCachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                    ArrayList protocolList;
                    Trace.Write("GetPendingItems");
                    pendingItems.DataSource = protocolList = protocolManager.GetPendingItems(currentPageIndex*pendingItems.PageSize, Math.Min(currentPageIndex*pendingItems.PageSize + pendingItems.PageSize, protocolManager.Count), DataAccess.ConnectionString, userContext.DomainUserId);
                    try
                    {
                        Trace.Write("DataBind");
                        pendingItems.DataBind();
                        Trace.Write("Done");
                    }
                    catch
                    {
                        throw new Exception("Your Search is out of context. Please use a different search criteria.");
                    }

                    if (protocolList.Count == 0)
                    {
                        HideGrid();
                    }
                    else
                    {
                        ShowGrid();
                        if (CurrentPageIndex == 0)
                        {
                            InitializePager();
                        }
                        ManagePagination();
                        ManageNavigationLinks();
                    }
                }
                else
                {
                    HideGrid();
                }
            }
            catch (Exception e)
            {
                ExceptionReport.WriteToEventLog("Pending Apps LoadDataGrid", e, true, ExceptionReport.ReportType.Error);
                gridContainer.Visible = false;
                searchCriteriaDisplay.Visible = false;
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = "Your Search is out of context. Please use a different search criteria.";
            }
        }

        /// <summary>
        /// Initilize the first record, last record and current page values for the pager controls.
        /// Set the current page index to 0 and manage navigation links.
        /// </summary>
        private void InitializePager()
        {
            bottomPager.FirstRecord = topPager.FirstRecord = 1;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(pendingItems.PageSize, pendingItems.Items.Count);
            bottomPager.CurrentPage = topPager.CurrentPage = 1;
            CurrentPageIndex = 0;
            ManageNavigationLinks();
        }

        /// <summary>
        /// Enables or Disables links to other pages within the grid
        /// </summary>
        private void ManageNavigationLinks()
        {
            bottomPager.EnableFirstPage = topPager.EnableFirstPage =
                bottomPager.EnablePreviousPage = topPager.EnablePreviousPage =
                    (pendingItems.CurrentPageIndex != 0);

            bottomPager.EnableLastPage = topPager.EnableLastPage =
                bottomPager.EnableNextPage = topPager.EnableNextPage =
                    (pendingItems.CurrentPageIndex != (topPager.PageCount - 1));
        }

        private void ManagePagination()
        {
            int currentPageIndex = CurrentPageIndex;
            pendingItems.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*pendingItems.PageSize;
            bottomPager.FirstRecord = topPager.FirstRecord = startIndex + 1;

            int lastRecord = ProtocolManagerInstance.Count;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(startIndex + pendingItems.PageSize, lastRecord);
        }

        /// <summary>
        /// This method shows the grid
        /// </summary>
        private void ShowGrid()
        {
            gridContainer.Visible = true;
            annunciator.Message = string.Empty;
        }

        /// <summary>
        /// This method hides the grid
        /// </summary>
        private void HideGrid()
        {
            gridContainer.Visible = false;
            annunciator.Message = "The search criteria yielded no results.";
        }

        /// <summary>
        /// Uncaches all objects with data for this page.
        /// </summary>
        private void PurgeCache()
        {
            System.Diagnostics.Trace.WriteLine("Purging PendingApplications...");
            Policy.ResultsCache.PurgeObject(PrevailingCachePolicy);
            humansSubNavigation.Reset();
            animalsSubNavigation.Reset();
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Initializes components used by the page.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            //InitializeComponent();
            base.PageCacheKey = (ModuleName == InsightUtilities.Constants.Modules.Humans) ? Keys.PendingApplicationsPageKey :
                                                                                               Keys.AnimalsPendingApplicationsPageKey;
            base.OnInit(e);

            humansSubNavigation.Navigate += new CommandEventHandler(OnSubNavigate);
            this.downloadBar.FailedAction += new CommandEventHandler(OnDownloadFailed);

            newProtocolBar.ModuleName = ModuleName;
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Clear Selection" buttion is clicked upon.
        /// The control clears the criteria (specific to this module).
        /// Since in the page life-cycle, the Load occurs before the Clear event, we have to instigate a re-load of the
        /// data grid to refelect the fact that the search criteria has been cleared.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            pendingItems.DataSource = null;
            pendingItems.DataBind();
            HideGrid();
            annunciator.Message = @"Verify the search criteria and click the 'Search' button to return the matching records.";
            // We need to completely clear the search criteria for the module because we 
            // depend on version 0 to know if it's ok to load the grid.  We can't set the version
            // back to 0 due to the design of search context.
            CommonSearchContext searchContext = ((GridPage) Page).PrevailingCachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            searchContext.ClearModuleSearchCriteria();
        }

        /// <summary>
        /// Initiates the search by calling PerformSearch
        /// </summary>
        /// <param name="args">Argument associated with the event (contains the search criteria dictionary)</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            try
            {
                PerformSearch();
            }
            catch (EvaluateException ex)
            {
                gridContainer.Visible = false;
                if (ex.Message.IndexOf("Error in Like operator:") >= 0)
                {
                    DisplayExceptionReport(annunciator,
                        "Search Error: Wild card character(%) can either be specified at the beginning or end of the criterion.");
                }
                else
                {
                    DisplayExceptionReport(annunciator, ex, true);
                }
            }
            catch (Exception ex)
            {
                gridContainer.Visible = false;
                DisplayExceptionReport(annunciator, ex, true);
            }
        }

        /// <summary>
        /// The version property of the searchcriteria is used to determine if criteria has been
        /// set (even if open ended).  We set to 1 when we perform search, and 0 when we clear 
        /// selections.  If actual criteria is set (not open ended), versioning is handled by
        /// the search context.
        /// </summary>
        /// <param name="version"></param>
        private void SetSearchCriteriaVersion(int version)
        {
            CommonSearchContext searchContext = ((GridPage) Page).PrevailingCachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
            searchCriteria.Version = version;
            searchContext.SetSearchCriteria(Page.Request.Url.ToString(), searchCriteria, searchContext.GetSearchCriteria(Page.Request.Url.ToString()));
        }

        /// <summary>
        /// Retrieves the CommonSearchContext from the cache.  If it's not null, a search is initiated on the
        /// PendingApplicationSummaries object using the search criteria; the fact that the summaries have been 
        /// filtered gets cached, the dataGrid page gets reset to 0, the grid gets loaded and the pagers get initialized.
        /// </summary>
        private void PerformSearch()
        {
            Policy.ResultsCache.PurgeObject(PrevailingCachePolicy);
            CommonSearchContext searchContext = PrevailingCachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            SetSearchCriteriaVersion(1);
            CurrentPageIndex = pendingItems.CurrentPageIndex = 0;
            LoadDataGrid();
            InitializePager();
        }

        /// <summary>
        /// On non-postbacks, search criteria is retrieved and the datagrid is loaded with protocols.  The page's 
        /// search criteria version is compared to the search context's search criteria version.  If they're 
        /// different, the protocols and protocol ids are unloaded from the cache before loading the datagrid.  
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                /*at098 - 01/23/2008
                 * Changes for SQL Reports
                 * To Do: move it to the lower block
                 */
                if (ModuleName == InsightUtilities.Constants.Modules.Humans)
                {
                    downloadBar.SQLReportName = SSRSRequest.ReportNames.Humans.PendingApplications;
                }
                else if (ModuleName == InsightUtilities.Constants.Modules.Animals)
                {
                    downloadBar.SQLReportName = SSRSRequest.ReportNames.Animals.PendingApplications;
                }

                annunciator.EnableViewState = false;
                breadCrumb.Add(
                    "Pending Applications",
                    Settings.GetKeyValue("SubNavigation.Humans.PendingApplicationsURL", ""),
                    Settings.GetKeyValue("BreadCrumb.SummaryPageLevel", 1));

                SetAnimalsOrHumansControls();

                if (!IsPostBack && postbackGuard.IsValid)
                {
                    SortColumn = SortColumn ?? ((ModuleName == InsightUtilities.Constants.Modules.Humans) ? HumansSortColumn : AnimalsSortColumn);

                    Policy.ResultsCache.PurgeObject(PrevailingCachePolicy);
                    //CurrentPageIndex = 0;
                    pendingItems.PageSize = Settings.GetKeyValue("HumansDataGrid.ItemsPerPage", 20);

                    ((ExpansionToggler) humansSearchContainer.FindControl("humansExpansionToggler")).HelpText =
                        ((ExpansionToggler) animalsSearchContainer.FindControl("animalsExpansionToggler")).HelpText =
                            InsightUtilities.Constants.SearchHelpText + InsightUtilities.Constants.FilterHelpText;
                    if (IsOkayToLoadGrid)
                    {
                        LoadDataGrid();
                    }
                }
            }
            catch (EvaluateException ex)
            {
                if (ex.Message.IndexOf("Error in Like operator:") >= 0)
                {
                    gridContainer.Visible = false;
                    DisplayExceptionReport(annunciator,
                        "Search Error: Wild card character(%) can either be specified at the beginning or end of the criterion.");
                }
                else
                {
                    DisplayExceptionReport(annunciator, ex, true);
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(annunciator, ex, true);
            }
        }

        /// <summary>
        /// During data binding of the grid, a tooltip with the full title is associated with the
        /// shortened version that appears on the screen.  For every record, the corresponding lock/unlock
        /// icon is bound here, and if there are any IRB notes, a note icon is bound.  Associated with the
        /// note icon, javascript is created to launch the note in a pop-up
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            // add in lock and note icons
            if ((e.Item.ItemType == ListItemType.Item ||
                e.Item.ItemType == ListItemType.AlternatingItem))
            {
                e.Item.Cells[(int) ColumnIndex.Title].ToolTip =
                    ((PendingApplicationSummary) e.Item.DataItem).Title;
                e.Item.Cells[(int) ColumnIndex.SponsorName].ToolTip =
                    ((PendingApplicationSummary) e.Item.DataItem).TruncatedSponsorName;

                Control image = e.Item.Cells[(int) ColumnIndex.LockIcon].FindControl("lockUnlock");
                if (null != image)
                {
                    ((Image) image).ImageUrl = (((PendingApplicationSummary) e.Item.DataItem).IsLocked) ?
                                                                                                            "~/Images/Lock.gif" : "~/Images/Unlock.gif";
                }

                if (((PendingApplicationSummary) e.Item.DataItem).Notification)
                {
                    Control notesImage = e.Item.Cells[(int) ColumnIndex.NoteIcon].FindControl("reviewNotes");
                    if (null != image)
                    {
                        notesImage.Visible = true;
                        ((ImageButton) notesImage).ImageUrl = "~/Images/Note.gif";
                        ((ImageButton) notesImage).CommandName = ViewIRBNotesCommand;
                    }
                }

                // handle creation of Workflow report icon, javscript and assignment of the javascript									

                if (e.Item.Cells[(int) ColumnIndex.ProtocolprocessId].Text != "0")
                {
                    ImageButton reportImage = e.Item.Cells[(int) ColumnIndex.WorkflowIcon].FindControl("workflowHistory") as ImageButton;
                    reportImage.Visible = true;
                    reportImage.ImageUrl = "~/Images/Note.gif";
                    reportImage.Attributes["onclick"] =
                        string.Format("window.open('{0}?PPId={1}', 'WorkflowReport', '{2}');return false;",
                            WorkFlowReportPage,
                            e.Item.Cells[(int) ColumnIndex.ProtocolprocessId].Text, features);
                }
            }
        }

        /// <summary>
        /// Occurs when the FirstPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the first page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnFirstPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = 0;
            LoadDataGrid();
        }

        /// <summary>
        /// Occurs when the LastPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the last page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnLastPage(object sender, CommandEventArgs e)
        {
            int lastPageIndex = topPager.PageCount - 1;
            CurrentPageIndex = lastPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Occurs when the NexttPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the next page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnNextPage(object sender, CommandEventArgs e)
        {
            ++CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Occurs when the PreviousPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the previous page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnPreviousPage(object sender, CommandEventArgs e)
        {
            --CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// This event is raised when the page index property is changed on the pager control.
        /// The page's DataGrid is reloaded with the data belonging to page specified by the index.
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnPageIndexChanged(object source, DataGridPageChangedEventArgs e)
        {
            pendingItems.CurrentPageIndex = e.NewPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Handles events raised by sorting the datagrid.  Processes the sort criteria and if the column to sort
        /// on is different than the column currently sorted on, the pending applications and their ids are unloaded 
        /// from the cache.  In all cases, the search criteria is retrieved, the grid is loaded with the protocols, 
        /// and the sort arrow is displayed on the appropriate column in the appropriate direction.  
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnSort(object source, DataGridSortCommandEventArgs e)
        {
            if (e.SortExpression != string.Empty)
            {
                ProtocolManager protocolManager = ResultsCache;
                if (protocolManager != null)
                {
                    sortAscending = (protocolManager.SortColumn == e.SortExpression) ? !protocolManager.SortAscending : false;
                }
                SortColumn = e.SortExpression;
                PerformSearch();
            }
        }

        /// <summary>
        /// Handles events raised by clicking on items in the grid.  If the command associated with the event
        /// is "SelectProtocol", data relevant to the details page is stored to session and the page
        /// is travelled to
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                if (e.CommandName == "SelectProtocol")
                {
                    Hashtable outgoingData = new Hashtable();
                    outgoingData.Add(Keys.ProtocolIdKey, e.Item.Cells[(int) ColumnIndex.Id].Text);
                    outgoingData.Add(Keys.ProtocolAccessKey, e.Item.Cells[(int) ColumnIndex.AccessLevel].Text);
                    string processId = e.Item.Cells[(int) ColumnIndex.ProtocolprocessId].Text;
                    outgoingData.Add(Keys.ProtocolProcessIdKey, processId);
                    PrevailingPageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                    //The following key is used to determine whether or not the protocol details page should show up the new process bar.
                    //Note:New process creation bar should show up only if the protocol is selected from the active protocols page.
                    PrevailingPageCachePolicy.Cache(Keys.ShowNewProcessBarKey, false);

                    if (processId != "0" && !processId.Equals(string.Empty))
                    {
                        PrevailingCachePolicy.Cache(Keys.ProtocolProcessKey, ProtocolProcess.GetProtocolProcess(DataAccess.ConnectionString, Int32.Parse(processId), PrevailingCachePolicy, null));
                    }

                    Image image = (e.Item.Cells[(int) ColumnIndex.LockIcon]).FindControl("lockUnlock") as Image;

                    if ((image.ImageUrl == "~/Images/Unlock.gif") && (int.Parse(processId) != 0))
                    {
                        PurgeCache();
                        Page.Response.Redirect(
                            Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolProcessOverviewURL", ""), false);
                    }
                    else
                    {
                        PurgeCache();
                        Page.Response.Redirect(
                            Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolDetailsURL", ""), false);
                    }
                }

                else if (e.CommandName == ViewIRBNotesCommand)
                {
                    string mimeType = Helper.GetMimeType(".rtf");
                    if (mimeType != null)
                    {
                        Response.ContentType = mimeType;
                    }

                    Response.AppendHeader("content-disposition",
                        string.Format("attachment; filename={0}.rtf", Guid.NewGuid()));

                    Response.Write(((string) DataAccess.ExecuteScalar(DataAccess.GetConnectionString(),
                        "GetNotification",
                        DataAccess.BuildSqlParameterArray("@boardReviewId", SqlDbType.Int,
                            e.Item.Cells[(int) ColumnIndex.BoardReviewId].Text))));

                    // Call this to end the request instead of Response.End see MS KB 312629
                    HttpContext.Current.ApplicationInstance.CompleteRequest();
                }
            }
            catch (Exception ex)
            {
                ExceptionReport.WriteToEventLog("Pending Apps OnItemCommand", ex, true, ExceptionReport.ReportType.Error);

                if (e.Item.DataItem != null)
                {
                    annunciator.Message =
                        String.Format("{0} while attempting to transfer to page {1}, ProtocolID =  {2}",
                            ExceptionReport.GetExceptionInfo(ex, false),
                            Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolDetailsURL", ""),
                            ((PendingApplicationSummary) e.Item.DataItem).ProtocolID);
                }
                else
                {
                    annunciator.Message =
                        String.Format("{0} while attempting to transfer to page {1}",
                            ExceptionReport.GetExceptionInfo(ex, false),
                            Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolDetailsURL", ""));
                }
            }
        }

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// If the item being created is the data grid header, do the following:
        /// Add the appropriate sort symbol to denote ascending/descending sequence for the current sort column.
        /// This requires us to locate the cell which corresponding to the column within the collection of TableCell
        /// maintained by the DataGridItem which is under creation. That collection is indexed numerically, the value being
        /// the position of the column within the columns collection maintained by the data grid.
        /// One simple way to do this is to create static mapping between the name of the column and its index. However, this
        /// suffers from the shortcoming that if the sequence of columns is changed on the page, the static binding MUST
        /// be changed too. If they get out of sync, we would be sorting on inappropriate columns!
        /// To avoid this, and to render the code independent of how the page gets managed, we will build a Hashtable of
        /// column indeces, keyed by the sort expression of each column. That way, we could do a quick lookup to get the
        /// index of a column and set the sort symbol on that column.
        /// If the item being created is a data row item, disable its view state.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Header)
            {
                ProtocolManager protocolManager = ProtocolManagerInstance;
                Label sortSymbol = new Label();
                sortSymbol.Text = protocolManager.SortAscending ? InsightUtilities.Constants.SortAscendingText : InsightUtilities.Constants.SortDescendingText;
                sortSymbol.Font.Name = InsightUtilities.Constants.SortSymbolFontName;

                Hashtable columnMap = new Hashtable();
                foreach (DataGridColumn column in pendingItems.Columns)
                {
                    columnMap[column.SortExpression] = pendingItems.Columns.IndexOf(column);
                }

                string sortColumn = protocolManager.SortColumn;
                if (columnMap.ContainsKey(sortColumn))
                {
                    e.Item.Cells[(int) columnMap[sortColumn]].Controls.Add(sortSymbol);
                }
            }
            else if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
            {
                foreach (TableCell c in e.Item.Cells)
                {
                    if (c.Equals(e.Item.Cells[(int) ColumnIndex.Id]) ||
                        c.Equals(e.Item.Cells[(int) ColumnIndex.AccessLevel]) ||
                            c.Equals(e.Item.Cells[(int) ColumnIndex.ProtocolprocessId]) ||
                                c.Equals(e.Item.Cells[(int) ColumnIndex.LockIcon]) ||
                                    c.Equals(e.Item.Cells[(int) ColumnIndex.NoteIcon]) ||
                                        c.Equals(e.Item.Cells[(int) ColumnIndex.WorkflowIcon]))
                    {
                        c.EnableViewState = true;
                    }
                    else
                    {
                        c.EnableViewState = false;
                    }
                }
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        /// <summary>
        /// Purges the cache before the humans subnavigation header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnSubNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = AnnunciatorTitle;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }

        private void SetAnimalsOrHumansControls()
        {
            SelectedSubNavigationLink = "Pending Applications";
            if (ModuleName == InsightUtilities.Constants.Modules.Humans)
            {
                humansSubNavigation.Visible = humansSearchContainer.Visible = true;
                animalsSearchContainer.Visible = animalsSubNavigation.Visible = false;
                humansSubNavigation.SelectedLink = "Pending Applications";
            }
            else
            {
                animalsSearchContainer.Visible = animalsSubNavigation.Visible = true;
                humansSubNavigation.Visible = humansSearchContainer.Visible = false;
                animalsSubNavigation.SelectedLink = "Pending Applications";
            }
        }

        #region Download Bar Handlers/Helpers

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        #endregion

        #endregion

        #region ColumnIndex Enum

        /// <summary>
        /// Provides indexes used in the datagrid for specific columns
        /// </summary>
        private enum ColumnIndex
        {
            /// <summary>id column index (hidden)</summary>
            Id,
            /// <summary>access level column index (hidden)</summary>
            AccessLevel,
            /// <summary>protocol # column index</summary>
            ProtocolNumber,
            /// <summary>pi's name column index</summary>
            PIName,
            /// <summary>title column index</summary>
            Title,
            /// <summary>sponsor name column index</summary>
            SponsorName,
            /// <summary>formsId column index</summary>
            FormsID,
            /// <summary>submission date column index</summary>
            SubmissionDate,
            /// <summary>board name column index</summary>
            BoardName,
            /// <summary>review type column index</summary>
            ReviewType,
            /// <summary>meeting date column index</summary>
            MeetingDate,
            /// <summary>board status column index</summary>
            BoardStatus,
            /// <summary>overall status column index</summary>
            LockIcon,
            /// <summary>irb notes column index</summary>
            NoteIcon,
            /// <summary>Workflow report column index</summary>
            WorkflowIcon,
            /// <summary>Workflow report column index</summary>
            ProtocolprocessId,
            /// <summary>BoardReviewId column index</summary>
            BoardReviewId
        }

        #endregion
    }
}